/*
 * Copyright 2007 Matt Jensen
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.jtell.internal.config.xml;

import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 * <code>SchemaResourceEntityResolver</code> is an implementation of the {@link EntityResolver} interface which resolves
 * references to the JTell schema in the distribution <code>jar</code> file. This allows us to validate the content of
 * our configuration files without downloading a schema file each time one is parsed.
 * </p>
 * <p>
 * <strong>Thread Safety</strong><br/>
 * Instances of this class are safe for multithreaded access. 
 * </p>
 */
public class SchemaResourceEntityResolver implements EntityResolver
{
    /**
     * <p>
     * Construct a {@link SchemaResourceEntityResolver} instance.
     * </p>
     */
    public SchemaResourceEntityResolver()
    {
        super();
    }

    /* inherit javadoc */
    public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException
    {
        final Matcher matcher = JTELL_XSD.matcher(systemId);
        final InputSource result;
        if (!matcher.matches())
        {
            result = null;
        }
        else
        {
            // Matches our pattern. Extract the XSD file name and attempt to load as a resource.
            final String xsdName = matcher.group(1);
            final InputStream xsdStream = getClass().getClassLoader().getResourceAsStream(xsdName);
            result = new InputSource(xsdStream);
        }
        return result;
    }

    /**
     * <p>
     * Pattern identifying JTell XSD files. When a matching system ID is encountered, match group 1 is extracted and
     * loaded from the root of the library JAR file.
     * </p>
     */
    private static final Pattern JTELL_XSD = Pattern.compile("^http://jtell\\.org/xsd/(\\S+\\.xsd)$");
}
